@@ -1,5 +1,27 @@
Revision history for Git-Repository
+1.20 Thu Jun 9 14:08:43 CEST 2011
+ [ENHANCEMENTS]
+ - None. It's as good as 1.19, without the stupid test fail.
+ [TESTS]
+ - one test always failed if run outside of a git repository,
+ so I didn't detect it, but all testers did :-(
+ Kazuhiro Shibuya provided a patch!
+
+1.19 Wed Jun 8 23:39:22 CEST 2011
+ [ENHANCEMENTS]
+ - new final_output() method to Git::Repository::Command,
+ that does the git-specific error checking when collecting
+ the final output
+ - Git::Repository::Log::Iterator will now properly die/warn
+ when the log command is incorrect (thanks to Lasse Makholm
+ for the bug report and proposed patch)
+ - Git::Repository::Command now supports an arrayref as the 'git'
+ option value, thus allowing calling wrappers like sudo
+ (thanks to Dominic Humphries for the initial patch)
+ [DOCUMENTATION]
+ - moved the HOWTO part of the doc to Git::Repository::Tutorial
+
1.18 Sat Apr 16 13:47:26 CEST 2011
[ENHANCEMENTS]
- the create() method was fragile (parsing the output of
@@ -6,6 +6,7 @@ lib/Git/Repository/Log.pm
lib/Git/Repository/Log/Iterator.pm
lib/Git/Repository/Plugin.pm
lib/Git/Repository/Plugin/Log.pm
+lib/Git/Repository/Tutorial.pod
lib/Test/Git.pm
Makefile.PL
MANIFEST This list of files
@@ -19,7 +20,9 @@ t/07-version.t
t/10-new_fail.t
t/11-create.t
t/12-create.t
+t/13-sudo.t
t/20-simple.t
+t/21-submodule.t
t/22-backward.t
t/25-plugins.t
t/30-log.t
@@ -30,3 +33,4 @@ t/Git/Repository/Plugin/Hello2.pm
t/MyGit/Hello.pm
t/pod-coverage.t
t/pod.t
+t/sudo.pl
@@ -15,16 +15,16 @@ name: Git-Repository
provides:
Git::Repository:
file: lib/Git/Repository.pm
- version: 1.18
+ version: 1.20
Git::Repository::Command:
file: lib/Git/Repository/Command.pm
- version: 1.12
+ version: 1.13
Git::Repository::Log:
file: lib/Git/Repository/Log.pm
version: 1.01
Git::Repository::Log::Iterator:
file: lib/Git/Repository/Log/Iterator.pm
- version: 1.00
+ version: 1.01
Git::Repository::Plugin:
file: lib/Git/Repository/Plugin.pm
version: 1.01
@@ -44,4 +44,4 @@ requires:
resources:
license: http://dev.perl.org/licenses/
repository: http://github.com/book/Git-Repository
-version: 1.18
+version: 1.20
@@ -13,7 +13,7 @@ use File::Spec;
use Config;
use System::Command;
-our $VERSION = '1.12';
+our $VERSION = '1.13';
our @ISA = qw( System::Command );
@@ -30,7 +30,10 @@ for my $attr (qw( cmdline )) {
# CAN I HAS GIT?
my %binary; # cache calls to _is_git
sub _is_git {
- my ($binary) = @_;
+ my ( $binary, @args ) = @_;
+
+ # git option might be an arrayref containing an executable with arguments
+ # Best that can be done is to check if the first part is executable
# compute cache key:
# - filename (path): path
@@ -75,7 +78,8 @@ sub _is_git {
if !( defined $git && -x $git );
# try to run it
- my ( $pid, $in, $out, $err ) = __PACKAGE__->spawn( $git, '--version' );
+ my ( $pid, $in, $out, $err )
+ = __PACKAGE__->spawn( $git, @args, '--version' );
my $version = <$out>;
# does it really look like git?
@@ -118,8 +122,12 @@ sub new {
# get and check the git command
my $git_cmd = ( map { exists $_->{git} ? $_->{git} : () } @o )[-1];
- $git_cmd = 'git' if !defined $git_cmd;
- my $git = _is_git($git_cmd);
+
+ # git option might be an arrayref containing an executable with arguments
+ # (e.g. [ qw( /usr/bin/sudo -u nobody git ) ] )
+ ( $git_cmd, my @args )
+ = defined $git_cmd ? ref $git_cmd ? @$git_cmd : ($git_cmd) : ('git');
+ my $git = _is_git($git_cmd, @args);
croak "git binary '$git_cmd' not available or broken"
if !defined $git;
@@ -128,7 +136,31 @@ sub new {
delete $ENV{TERM};
# spawn the command and re-bless the object in our class
- return bless System::Command->new( $git, @cmd, @o ), $class;
+ return bless System::Command->new( $git, @args, @cmd, @o ), $class;
+}
+
+sub final_output {
+ my ($self) = @_;
+
+ # get output / errput
+ my ( $stdout, $stderr ) = @{$self}{qw(stdout stderr)};
+ chomp( my @output = <$stdout> );
+ chomp( my @errput = <$stderr> );
+
+ # done with it
+ $self->close;
+
+ # exit codes: 128 => fatal, 129 => usage
+ my $exit = $self->{exit};
+ if ( $exit == 128 || $exit == 129 ) {
+ croak join( "\n", @errput ) || 'fatal: unknown git error';
+ }
+
+ # something else's wrong
+ if (@errput) { carp join "\n", @errput; }
+
+ # return the output
+ return wantarray ? @output : join "\n", @output;
}
1;
@@ -200,6 +232,12 @@ I<option> hashes. The recognized keys are:
The actual git binary to run. By default, it is just C<git>.
+In case the C<git> to be run is actually a command with parameters
+(e.g. when using B<sudo> or another command executer), the option value
+should be an array reference with the command and parameters, like this:
+
+ { git => [qw( sudo -u nobody git )] }
+
=item C<cwd>
The I<current working directory> in which the git command will be run.
@@ -241,6 +279,20 @@ number of attributes defined (see below).
Close all pipes to the child process, and collects exit status, etc.
and defines a number of attributes (see below).
+=head2 final_output()
+
+Collect all the output, and terminate the command.
+
+Returns the output as a string in scalar context,
+or as a list of lines in list context. Also accepts a hashref of options.
+
+Lines are automatically C<chomp>ed.
+
+If the Git command printed anything on stderr, it will be printed as
+warnings. If the git sub-process exited with status C<128> (fatal error),
+or C<129> (usage message), it will C<die()>.
+
+
=head2 Accessors
The attributes of a C<Git::Repository::Command> object are also accessible
@@ -9,7 +9,7 @@ use Git::Repository;
use Git::Repository::Command;
use Git::Repository::Log;
-our $VERSION = '1.00';
+our $VERSION = '1.01';
sub new {
my ( $class, @cmd ) = @_;
@@ -46,7 +46,7 @@ sub next {
}
# EOF
- return if !@records;
+ return $self->{cmd}->final_output() if !@records;
# the first two records are always the same, with --pretty=raw
my ( $header, $message, $extra ) = ( @records, '' );
@@ -0,0 +1,240 @@
+=head1 NAME
+
+Git::Repository::Tutorial - Control git from Perl using Git::Repository
+
+=head1 SYNOPSIS
+
+ use Git::Repository;
+
+ # do cool stuff with Git, using the following advice
+
+=head1 HOW-TO
+
+A C<Git::Repository> object represents an actual Git repository,
+against which you can I<run> commands.
+
+=head2 Obtain a Git::Repository object from an existing repository
+
+If your script is expected to run against a repository in the current
+directory (like most Git commands), let C<Git::Repository> handle
+the magic:
+
+ $r = Git::Repository->new();
+
+If the repository has a working copy (work tree):
+
+ $r = Git::Repository->new( work_tree => $dir );
+
+If the repository is a bare repository, or you prefer to provide
+the F<.git> directory location:
+
+ $r = Git::Repository->new( git_dir => $gitdir );
+
+If the work tree and the git directory are in unrelated locations,
+you can also provide both:
+
+ $r = Git::Repository->new( work_tree => $dir, git_dir => $gitdir );
+
+The constructor also accepts an option hash. The various options
+are detailed in the manual page for C<Git::Repository::Command>.
+
+=head2 Run any git command
+
+Git commands can be run against an existing C<Git::Repository> object,
+or against the class itself (in which case, git will try to deduce its
+context from the current directory and the environment).
+
+The pattern for running commands is always the same:
+
+ $r->run( $command => @arguments, \%options );
+
+The C<$command> and C<@arguments> are identical to those you'd pass to
+the C<git> command-line tool. The options hash contains options, as
+described in the manual page for C<Git::Repository::Command>.
+
+=head2 Create a new repository
+
+Sometime, you'll need to create the Git repository from scratch:
+
+ # git version 1.6.5 and above
+ Git::Repository->run( init => $dir );
+ $r = Git::Repository->new( work_tree => $dir );
+
+ # any older git requires the command to be run in the work tree,
+ # so we use the cwd option
+ Git::Repository->run( init => { cwd => $dir } );
+ $r = Git::Repository->new( work_tree => $dir );
+
+Note that the old C<create()> method is obsolete, warns and will be removed
+in a future version.
+
+=head2 Clone a repository
+
+Cloning works the same way:
+
+ Git::Repository->run( clone => $url => $dir );
+ $r = Git::Repository->new( $dir );
+
+=head2 Run a simple command
+
+When you don't really care about the output of the command, just call
+it:
+
+ $r->run( add => '.' );
+ $r->run( commit => '-m', 'my commit message' );
+
+In case of an error or warning, C<Git::Repository> will C<croak()> or
+C<carp()> appropriately.
+
+=head2 Process normal and error output
+
+The C<run()> command doesn't capture stderr: it only warns (or dies)
+if something was printed on it. To be able to actually capture error
+output, C<command()> must be used.
+
+ my $cmd = $r->command( @cmd );
+ my @errput = $cmd->stderr->getlines();
+ $cmd->close;
+
+C<run()> also captures all output at once, which can lead to unnecessary
+memory consumption when capturing the output of some really verbose
+commands.
+
+ my $cmd = $r->command( log => '--pretty=oneline', '--all' );
+ my $log = $cmd->stdout;
+ while (<$log>) {
+ ...;
+ }
+ $cmd->close;
+
+Of course, as soon as one starts reading and writing to an external
+process' communication handles, a risk of blocking exists.
+I<Caveat emptor>.
+
+=head2 Provide input on standard input
+
+Use the C<input> option:
+
+ my $commit = $r->run( 'commit-tree', $tree, '-p', $parent,
+ { input => $message } );
+
+=head2 Change the environment of a command
+
+Use the C<env> option:
+
+ $r->run(
+ 'commit', '-m', 'log message',
+ { env => {
+ GIT_COMMITTER_NAME => 'Git::Repository',
+ GIT_COMMITTER_EMAIL => 'book@cpan.org',
+ },
+ },
+ );
+
+See L<Git::Repository::Command> for other available options.
+
+=head2 Process the output of B<git log>
+
+When creating a tool that needs to process the output of B<git log>,
+you should always define precisely the expected format using the
+I<--pretty> option, and choose a format that is easy to parse.
+
+Assuming B<git log> will output the default format will eventually
+lead to problems, for example when the user's git configuration defines
+C<format.pretty> to be something else than the default of C<medium>.
+
+=head2 Process the output of B<git shortlog>
+
+B<git shortlog> behaves differently when it detects it's not attached
+to a terminal. In that case, it just tries to read some B<git log>
+output from its standard input.
+
+So this oneliner will hang, because B<git shortlog> is waiting for some
+data from the program connected to its standard input (the oneliner):
+
+ perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5 )'
+
+Whereas this one will "work" (as in "immediately return with no output"):
+
+ perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5, { input => "" } )'
+
+So, you need to give B<git shortlog> I<some> input (from B<git log>):
+
+ perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => { input => scalar Git::Repository->run( log => -5 ) } )'
+
+If the log output is large, you'll probably be better off with something
+like the following:
+
+ use Git::Repository;
+
+ # start both git commands
+ my $log = Git::Repository->command('log')->stdout;
+ my $cmd = Git::Repository->command( shortlog => -ens );
+
+ # feed one with the output of the other
+ my $in = $cmd->stdin;
+ print {$in} $_ while <$log>;
+ close $in;
+
+ # and do something with the output
+ print $cmd->stdout->getlines;
+
+=head2 Wrap git in a sudo call
+
+If for a given repository you want to wrap all calls to git in a C<sudo>
+call, you can use the C<git> option with an array ref:
+
+ my $r = Git::Repository->new( { git => [qw( sudo -u nobody git )] } );
+
+In this case, every call to git from C<$r> will actually call
+C<sudo -u nobody git>.
+
+=head2 Use submodules
+
+Because C<Git::Repository> automatically sets the C<GIT_DIR> and
+C<GIT_WORK_TREE> environment variables, some C<submodule> sub-commands
+may fail. For example:
+
+ $r->run( submodule => add => $repository => 'sub' );
+
+will give the following error:
+
+ error: pathspec 'sub' did not match any file(s) known to git.
+
+To avoid this error, you should enforce the removal of the C<GIT_WORK_TREE>
+variable from the environment in which the command is run:
+
+ $r->run(
+ submodule => add => $repository => 'sub',
+ { env => { GIT_WORK_TREE => undef } }
+ );
+
+Note that C<System::Command> version 1.04 is required to be able to remove
+variables from the environment.
+
+=head2 Sort git versions
+
+Basically, you need to recreate the C<cmp> operator for Git versions,
+using the I<private> C<_version_gt()> method (which accepts two parameters):
+
+ @sorted_versions = sort {
+ Git::Repository::_version_gt( $a, $b )
+ || -Git::Repository::_version_gt( $b, $a )
+ } @versions;
+
+
+=head1 AUTHOR
+
+Philippe Bruhat (BooK), C<< <book at cpan.org> >>
+
+=head1 COPYRIGHT
+
+Copyright 2010-2011 Philippe Bruhat (BooK), all rights reserved.
+
+=head1 LICENSE
+
+This documenation is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
@@ -11,7 +11,7 @@ use Scalar::Util qw( looks_like_number );
use Git::Repository::Command;
-our $VERSION = '1.18';
+our $VERSION = '1.20';
# a few simple accessors
for my $attr (qw( git_dir work_tree options )) {
@@ -109,7 +109,7 @@ sub new {
$self->{git_dir} = $git_dir if defined $git_dir;
# in a non-bare repository, the work tree is just above the gitdir
- if ( $self->run(qw( config core.bare )) ne 'true' ) {
+ if ( $self->run(qw( config --bool core.bare )) ne 'true' ) {
$self->{work_tree}
= _abs_path( File::Spec->updir, $self->{git_dir} );
}
@@ -191,25 +191,8 @@ sub run {
my $command
= Git::Repository::Command->new( ref $self ? $self : (), @cmd );
- # get output / errput
- my ( $stdout, $stderr ) = @{$command}{qw(stdout stderr)};
- chomp( my @output = <$stdout> );
- chomp( my @errput = <$stderr> );
-
- # done with it
- $command->close;
-
- # exit codes: 128 => fatal, 129 => usage
- my $exit = $command->{exit};
- if ( $exit == 128 || $exit == 129 ) {
- croak join( "\n", @errput ) || 'fatal: unknown git error';
- }
-
- # something else's wrong
- if (@errput) { carp join "\n", @errput; }
-
- # return the output
- return wantarray ? @output : join "\n", @output;
+ # return the output or die
+ return $command->final_output;
}
#
@@ -350,7 +333,7 @@ command, whether I<porcelain> or I<plumbing>, including bidirectional
commands such as C<git commit-tree>.
A C<Git::Repository> object simply provides context to the git commands
-being run. Is it possible to call the C<command()>and C<run()> methods
+being run. It is possible to call the C<command()> and C<run()> methods
against the class itself, and the context (typically I<current working
directory>) will be obtained from the options and environment.
@@ -364,6 +347,11 @@ object, they will be overriden by the object's C<git_dir> and
C<work_tree> attributes, respectively. It is however still possible to
override them if necessary, using the C<env> option.
+C<Git::Repository> requires at least Git 1.5.0, and is expected to support
+any later version.
+
+See C<Git::Repository::Tutorial> for more code examples.
+
=head1 CONSTRUCTORS
There are two ways to create C<Git::Repository> objects:
@@ -470,7 +458,7 @@ Lines are automatically C<chomp>ed.
If the git command printed anything on stderr, it will be printed as
warnings. If the git sub-process exited with status C<128> (fatal error),
-C<run()> will C<die()>.
+or C<129> (usage message), C<run()> will C<die()>.
=head2 git_dir()
@@ -555,119 +543,6 @@ supported a given feature. The precise commit in git.git at which a given
feature was added doesn't mean as much as the release branch in which that
commit was merged.
-=head1 HOW-TO
-
-=head2 Create a new repository
-
- # git version 1.6.5 and above
- my $r = Git::Repository->create( init => $dir );
-
- # any older git will need two steps
- chdir $dir;
- my $r = Git::Repository->create( 'init' );
-
-=head2 Clone a repository
-
- my $r = Git::Repository->create( clone => $url => $dir );
-
-=head2 Run a simple command
-
- $r->run( add => '.' );
- $r->run( commit => '-m', 'my commit message' );
-
-=head2 Process normal and error output
-
-The C<run()> command doesn't capture stderr: it only warns (or dies)
-if something was printed on it. To be able to actually capture error
-output, C<command()> must be used.
-
- my $cmd = $r->command( @cmd );
- my @errput = $cmd->stderr->getlines();
- $cmd->close;
-
-C<run()> also captures all output at once, which can lead to unnecessary
-memory consumption when capturing the output of some really verbose
-commands.
-
- my $cmd = $r->command( log => '--pretty=oneline', '--all' );
- my $log = $cmd->stdout;
- while (<$log>) {
- ...;
- }
- $cmd->close;
-
-Of course, as soon as one starts reading and writing to an external
-process' communication handles, a risk of blocking exists.
-I<Caveat emptor>.
-
-=head2 Provide input on standard input
-
-Use the C<input> option:
-
- my $commit = $r->run( 'commit-tree', $tree, '-p', $parent,
- { input => $message } );
-
-=head2 Change the environment of a command
-
-Use the C<env> option:
-
- $r->run(
- 'commit', '-m', 'log message',
- { env => {
- GIT_COMMITTER_NAME => 'Git::Repository',
- GIT_COMMITTER_EMAIL => 'book@cpan.org',
- },
- },
- );
-
-See L<Git::Repository::Command> for other available options.
-
-=head2 Process the output of B<git log>
-
-When creating a tool that needs to process the output of B<git log>,
-you should always define precisely the expected format using the
-I<--pretty> option, and choose a format that is easy to parse.
-
-Assuming B<git log> will output the default format will eventually
-lead to problems, for example when the user's git configuration defines
-C<format.pretty> to be something else than the default of C<medium>.
-
-=head2 Process the output of B<git shortlog>
-
-B<git shortlog> behaves differently when it detects it's not attached
-to a terminal. In that case, it just tries to read some B<git log>
-output from its standard input.
-
-So this oneliner will hang, because B<git shortlog> is waiting for some
-data from the program connected to its standard input (the oneliner):
-
- perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5 )'
-
-Whereas this one will "work" (as in "immediately return with no output"):
-
- perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => -5, { input => "" } )'
-
-So, you need to give B<git shortlog> I<some> input (from B<git log>):
-
- perl -MGit::Repository -le 'print scalar Git::Repository->run( shortlog => { input => scalar Git::Repository->run( log => -5 ) } )'
-
-If the log output is large, you'll probably be better off with something
-like the following:
-
- use Git::Repository;
-
- # start both git commands
- my $log = Git::Repository->command('log')->stdout;
- my $cmd = Git::Repository->command( shortlog => -ens );
-
- # feed one with the output of the other
- my $in = $cmd->stdin;
- print {$in} $_ while <$log>;
- close $in;
-
- # and do something with the output
- print $cmd->stdout->getlines;
-
=head1 PLUGIN SUPPORT
C<Git::Repository> intentionally has only few methods.
@@ -715,6 +590,20 @@ revision history of a project. A lot of those commands can output
huge amounts of data, which I need to be able to process in chunks.
Some of these commands also expect to receive input.
+What follows is a short list of "missing features" that I was looking
+for when I looked at the existing Git wrappers on CPAN. They are the
+"rational" reason for writing my own (the real reason being of course
+"I thought it would be fun, and I enjoyed doing it").
+
+Even though it works well for me and others, C<Git::Repository> has its
+own shortcomings: it I<is> a I<low-level interface to Git commands>,
+anything complex requires you to deal with input/output handles,
+it provides no high-level interface to generate actual Git commands
+or process the output of commands (but have a look at the plugins),
+it doesn't fully work under Win32 yet, etc. One the following modules
+may therefore be better suited for your needs, depending on what you're
+trying to achieve.
+
=head2 Git.pm
Git.pm is not on CPAN. It is usually packaged with Git, and installed with
@@ -730,9 +619,11 @@ L<http://kerneltrap.org/mailarchive/git/2008/10/24/3789584>
=head2 Git::Class
Depends on Moose, which seems an unnecessary dependency for a simple
-wrapper around Git.
+wrapper around Git. The startup penalty could become significant for
+command-line tools.
-Although it supports C<git init> and C<git clone>, it is mostly aimed at
+Although it supports C<git init> and C<git clone>
+(and has methods to call any Git command), it is mostly aimed at
porcelain commands, and provides no way to control bidirectional commands
(such as C<git commit-tree>).
@@ -748,11 +639,11 @@ Philippe Bruhat (BooK), C<< <book at cpan.org> >>
=head1 BUGS
-On Win32, in some cases of failure of the underlying Git command,
-the C<run()> method is not able to catch the error output on STDERR.
-In those cases, C<Git::Repository> will croak C<fatal: unknown git error>
-instead of the original Git error message. Bugfixes and explanations
-are very welcome.
+Since version 1.17, C<Git::Repository> delegates the actual command
+execution to C<System::Command>. Win32 support for that module is
+currently very bad (the test suite hangs in a few places).
+If you'd like better Win32 support for C<Git::Repository>, help me improve
+C<System::Command>!
Please report any bugs or feature requests to C<bug-git-repository at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Git-Repository>. I will be notified, and then you'll
@@ -49,12 +49,13 @@ for my $t (@true) {
# helper routine to build a fake fit binary
sub fake_git {
my ($version) = @_;
- my ( $fh, $filename ) = tempfile( MSWin32 ? ( SUFFIX => '.bat' ) : () );
+ my ( $fh, $filename ) =
+ tempfile( UNLINK => 1, MSWin32 ? ( SUFFIX => '.bat' ) : () );
print {$fh} MSWin32 ? << "WIN32" : << "UNIX";
\@echo git version $version
WIN32
-#!/bin/sh
-$^X -le 'print "git version $version"'
+#!$^X
+print "git version $version\\n"
UNIX
close $fh;
chmod 0755, $filename;
@@ -0,0 +1,15 @@
+use strict;
+use warnings;
+use Test::More;
+use Test::Git;
+use File::Spec;
+
+has_git();
+
+plan tests => 1;
+
+# test using a wrapper
+my $sudo = File::Spec->catfile( t => 'sudo.pl' );
+my $out = Git::Repository->run( qw( a b ), { git => [ $^X, $sudo, 'c' ] } );
+is( $out, 'c a b', 'wrapper called correctly' );
+
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+use Test::More;
+use Test::Git;
+use Git::Repository;
+
+plan skip_all =>
+ "Removing environment variables requires System::Command 1.04, this is only $System::Command::VERSION"
+ if $System::Command::VERSION < 1.04;
+
+plan tests => 1;
+
+# create a small repository
+my $s = test_repository;
+my $tree = $s->run( mktree => { input => '' } );
+my $commit = $s->run( 'commit-tree' => $tree, { input => 'empty tree' } );
+$s->run( 'update-ref', 'refs/heads/master' => $commit );
+
+# now test adding a submodule
+my $r = test_repository;
+$r->run(
+ submodule => add => $s->work_tree => 'sub',
+ { env => { GIT_WORK_TREE => undef } }
+);
+
+# do the test
+my $status = $r->run('submodule', 'status', 'sub' );
+is( $status, "-$commit sub", 'git submodule status' );
+
@@ -98,6 +98,24 @@ check_commit( 2 => $log[0] );
chdir $home;
+# try a command that fails (fatal)
+BEGIN { $tests += 2 }
+ok( !eval { @log = $r->log('zlonk') }, q{log('zlonk') failed} );
+like(
+ $@,
+ qr/^fatal: ambiguous argument 'zlonk': unknown revision or path not in/,
+ 'unknown revision or path'
+);
+
+# try a command that returns a git error (usage)
+BEGIN { $tests += 2 }
+ok( !eval { @log = $r->log('--bam') }, q{log('--bam') failed} );
+like(
+ $@,
+ qr/^fatal: unrecognized argument: --bam at/,
+ 'unknown revision or path'
+);
+
# various options combinations
my @options;
@@ -125,10 +143,10 @@ DIFF
for my $o (@options) {
my ( $args, $extra, $minver ) = @$o;
- @log = $r->log(@$args);
SKIP: {
skip "git log @$args needs $minver, we only have $version", 13
if $minver && Git::Repository->version_lt($minver);
+ @log = $r->log(@$args);
is( scalar @log, 2, "2 commits for @$args" );
isa_ok( $_, 'Git::Repository::Log' ) for @log;
check_commit( 2 => $log[0], extra => $extra->[0] );
@@ -0,0 +1,5 @@
+#!/usr/bin/env perl
+
+# a tiny fake git wrapper
+print "@ARGV" =~ /version/ ? "git version 9.8.7\n" : "@ARGV\n";
+